package com.study_platform.consumer;

import com.alibaba.fastjson.JSONObject;
import com.study_platform.consumer.util.Game;
import com.study_platform.consumer.util.JwtAuthentication;
import com.study_platform.entity.User;
import com.study_platform.mapper.PkMapper;
import com.study_platform.mapper.UserMapper;
import com.study_platform.service.ProblemSolvingRecordService;
import com.study_platform.service.TestPaperService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

@Component
@ServerEndpoint("/websocket/{token}")
public class WebSocketServer {

    final public static ConcurrentHashMap<Integer, WebSocketServer> users = new ConcurrentHashMap<>();
    public static UserMapper userMapper;
    public static PkMapper pkMapper;

    @Autowired
    public void setRestTemplate(RestTemplate restTemplate) {
        WebSocketServer.restTemplate = restTemplate;
    }

    @Resource
    public void setTestPaperService(TestPaperService testPaperService){
        WebSocketServer.testPaperService = testPaperService;
    }
    public static TestPaperService testPaperService;

    @Resource
    public  void setProblemSolvingRecordService(ProblemSolvingRecordService problemSolvingRecordService) {
        WebSocketServer.problemSolvingRecordService = problemSolvingRecordService;
    }

    public static ProblemSolvingRecordService problemSolvingRecordService;
    private Game game = null;
    private final static String addPlayerUrl = "http://127.0.0.1:3001/player/add/";
    private final static String removePlayerUrl = "http://127.0.0.1:3001/player/remove/";
    private static RestTemplate restTemplate;
    private User user;
    private Session session = null;

    public static void startGame(Integer aId, Integer bId, Integer grade, String point) {
        System.out.println("startGame");
        User a = userMapper.selectById(aId);
        User b = userMapper.selectById(bId);

        Game game = new Game(a.getUserId(), b.getUserId(), grade, point);
        System.out.println("game生成");
        game.createQuestions();
        if(users.get(a.getUserId()) != null){
            users.get(a.getUserId()).game = game;
        }
        if(users.get(b.getUserId()) != null){
            users.get(b.getUserId()).game = game;
        }

        JSONObject jsonGame = new JSONObject();
        jsonGame.put("a_id", game.getPlayerA().getUserId());
        jsonGame.put("b_id", game.getPlayerB().getUserId());
        jsonGame.put("questions", game.getQuestions());
        jsonGame.put("a_answers", game.getPlayerA().getAnswer());
        jsonGame.put("b_answers", game.getPlayerB().getAnswer());

        JSONObject jsonPlayA = new JSONObject();
        jsonPlayA.put("event", "start-matching");
        jsonPlayA.put("opponent_username", b.getUserId());
        jsonPlayA.put("game", jsonGame);
        if (users.get(a.getUserId()) != null){
            users.get(a.getUserId()).sendMessage(jsonPlayA.toJSONString());
        }

        JSONObject jsonPlayB = new JSONObject();
        jsonPlayB.put("event", "start-matching");
        jsonPlayB.put("opponent_username", a.getUserId());
        jsonPlayB.put("game", jsonGame);
        if (users.get(b.getUserId()) != null){
            users.get(b.getUserId()).sendMessage(jsonPlayB.toJSONString());
        }

        game.start();
    }
    @Resource
    public void setPkMapper(PkMapper pkMapper){
        WebSocketServer.pkMapper = pkMapper;
    }
    @Resource
    public void setUserMapper(UserMapper userMapper) {
        WebSocketServer.userMapper = userMapper;
    }

    @OnOpen
    public void onOpen(Session session, @PathParam("token") String token) throws IOException {
        this.session = session;
        System.out.println("connected!");
        Integer userId = JwtAuthentication.getUserId(token);
        this.user = userMapper.selectById(userId);

        if (this.user != null) {
            users.put(userId, this);
        } else {
            this.session.close();
        }

        System.out.println(users);
    }

    @OnClose
    public void onClose() {
        System.out.println("disconnected!");
        if (this.user != null) {
            users.remove(this.user.getUserId());
        }
    }


    @OnMessage
    public void onMessage(String message, Session session) {  // 当做路由
        System.out.println("receive message!" + message);
        JSONObject data = JSONObject.parseObject(message);
        String event = data.getString("event");
        if ("start-matching".equals(event)) {
            Integer grade = Integer.valueOf(data.getString("grade"));
            String point = data.getString("point");
            startMatching(grade, point);
        } else if ("stop-matching".equals(event)) {
            stopMatching();
        } else if ("next".equals(event)) {
            next(data.getString("choice"));
        }
    }

    private void next(String choice) {
        System.out.println(choice);
        System.out.println();
        if (game.getPlayerA().getUserId().equals(user.getUserId())) {
            game.setNextAnswerStepA(choice);
        } else if (game.getPlayerB().getUserId().equals(user.getUserId())) {
            game.setNextAnswerStepB(choice);
        }

    }

    private void startMatching(Integer grade, String point) {
        System.out.println("start matching!");
        MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
        data.add("user_id", this.user.getUserId().toString());
        data.add("rating", this.user.getRating().toString());
        data.add("grade", grade.toString());
        data.add("point", point);
        restTemplate.postForObject(addPlayerUrl, data, String.class);
    }

    private void stopMatching() {
        System.out.println("stop matching");
        MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
        data.add("user_id", this.user.getUserId().toString());
        restTemplate.postForObject(removePlayerUrl, data, String.class);
    }


    @OnError
    public void onError(Session session, Throwable error){
        error.printStackTrace();
    }

    public void sendMessage(String message) {
        synchronized (this.session) {
            try {
                this.session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}